


#ifndef GEOMETRY_H
#define GEOMETRY_H

#include "Vec4.h"
#include "Matrix4.h"
#include "Aabb.h"
#include "HitData.h"
#include "Texture.h"

// STL includes
#include <string>
#include <cstring>
#include <iostream>
using std::string;

#include <vector>
using std::vector;


using namespace std;


class Ray;

struct Geometry
{		
	Geometry() : m_clockwiseWinding(true), m_builtList(false)
	{
		m_worldFromLocal.setIdentity();
		setTransform(m_worldFromLocal);
	}
	
	vector<Vec4> m_vertices;
	vector<Vec4> m_vertexNormals;
	vector<Vec4> m_UVs;
	
	// Needed to identify vertices as originally coming from the unfractured surface
	vector<bool> m_boundaryVertex;
	
	// 1 per-vertex, computed by summing normals of adjacent faces and re-normalizing. Useful for collision ops.
	vector<Vec4> m_smoothedNormals; 
	
	// This is the painted per-vertex color used as the seed for fracturing. It will be set from a loaded texture painted in Maya.
	// Via the vertex UVs, and the loaded texture map pixel values, we obtain a per-vertex color.
	vector<Vec4> m_rgbvertexWeight;
	
	void setVertexWeightFromTexture(Texture* texture);
	void setVertexWeightFromPerlinNoise(float scale=10.f, float alpha=1.0, float beta=1.0, int n=8);
	
	void computeSmoothedNormals();
	
	struct Triangle
	{
		Triangle()
		{
			for (int a=0; a<3; ++a)
			{
				m_vertex[a] = -1;
				m_vertexNormal[a] = -1;
			}
		}
		
		int m_vertex[3];
		int m_vertexNormal[3];
		int m_uvs[3];
	};

	vector<Triangle> m_triangles;
	
	void setTransform(const Matrix4& worldFromLocal);
	
	Aabb getTriangleAabb(int triIndex) const;

	// Intersect the given ray against the given triangle of this geometry, returning hit result
	HitData intersect(int triIndex, Ray& ray) const;

	// Needed to define outward normals, if no per-vertex normals
	bool m_clockwiseWinding;
	
	Aabb computeAabb() const;
	
	void compileDisplayList(bool wireframe);
	
	void draw(bool wireframe=false); 
	
private:
	
	bool m_builtList;
	
	Matrix4 m_worldFromLocal;
	Matrix4 m_invTranspose;
	
	GLuint m_displayList;
	
	inline void drawTriangle( const Geometry::Triangle& t, 
							   const vector<Vec4>& vertices, 
							   const vector<Vec4>& vertexNormals,
							   const vector<Vec4>& UVs) const;
	
};


#endif //GEOMETRY_H



